home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 2.0 Developer Kit / QuickTime 2.0 Developer Kit.iso / mac / MAC / Programming Stuff / Sample Code / Music Architecture / Embedding Instruments / BigEasy / BigEasyPPC.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-17  |  19.9 KB  |  949 lines  |  [TEXT/KAHL]

  1. /*
  2.     File:        BigEasyPPC.c
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Written by:    xxx put writers here xxx
  7.  
  8.     Copyright:    © 1992 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <2>      1/7/93    dvb        Compile under mpw.
  13.          <1>     1/20/92    dvb        first checked in
  14.  
  15. */
  16.  
  17. /* file: BigEasyPPC.c
  18.  *
  19.  * Started Mid 1991, more or less.
  20.  *
  21.  * A set of routines to quickly
  22.  * access some simple uses of PPC.
  23.  *
  24.  */
  25.  
  26. /*--------------------------
  27.     Protocol Notes
  28. --------------------------*/
  29. /*
  30.  
  31. Port creator type is always 'BigE', and the type is specified by
  32. the application.
  33.  
  34. When the BrowseAndConnect is used, the PPCBrowser checks port creator and
  35. type to match the connecting port (and only shows those that match), and
  36. also attempts to connect to the port with a userdata of 'test'. The server
  37. port rejects the connection attempt if the userdata is 'test', and
  38. returns 'test' as the Reject-reason.
  39.  
  40. */
  41.  
  42.  
  43. /*--------------------------
  44.     Inclusions
  45. --------------------------*/
  46.  
  47. #include "BigEasyPPC.h"
  48. #include <Errors.h>
  49. #include <Events.h>
  50.  
  51. /*--------------------------
  52.     Constants
  53. --------------------------*/
  54.  
  55. #define kEasyPPCPortCreator 'BigE'
  56.  
  57. enum
  58. /*
  59.  * For the filterproc to work, there must
  60.  * be an inform pending. The filterproc tests
  61.  * this by actually connecting to the proposed
  62.  * target, with userdata 'test'. The target sees this,
  63.  * and ignores the connection, and posts another 'Inform'
  64.  * just to make sure.
  65.  */
  66.     {
  67.     testConnection = 'test',
  68.     realConnection = 'real'
  69.     };
  70.  
  71. /*--------------------------
  72.     Globals
  73. --------------------------*/
  74.  
  75. Boolean gEverBrowsed = 0;            /* to remember where we are in the browser */
  76. LocationNameRec gTheLocation;
  77. PortInfoRec gThePortInfo;
  78.  
  79.  
  80. static EasyPPCSession gEasyFilterSession;        /* communicate with Filter Proc */
  81.  
  82. /*--------------------------
  83.     Prototypes
  84. --------------------------*/
  85.  
  86. static short BumpStringNumber(StringPtr s);
  87. static void HandleSomeErrors(EasyPPCSession es,EasyPPCPollResult *pollResult);
  88. static void InitializeClient(EasyPPCSession es,EasyPPCClient *clientPtr);
  89. static EasyPPCClient *FindClient(EasyPPCSession es,long sessRefNum);
  90. static void RemoveClientEntry(EasyPPCSession es,EasyPPCClient *clientPtr);
  91. static void PollEasyPPCClient(EasyPPCSession es,EasyPPCClient *clientPtr,
  92.         EasyPPCPollResult *pollResult);
  93. static EasyPPCClient *FindFreeClient(EasyPPCSession es);
  94.  
  95. static pascal void InformCompletion(PPCParamBlockPtr pb);
  96. static pascal Boolean EasyBrowserFilter (LocationNamePtr location, PortInfoPtr port);
  97.  
  98.  
  99. #define MoveString(src,dst) BlockMove(src,dst,src[0]+1)
  100.  
  101. /*--------------------------
  102.     Agedashi Dofu
  103. --------------------------*/
  104.  
  105. short BumpStringNumber(StringPtr s)
  106. /*
  107.  * Starting from string "string" make strings "string 00" through
  108.  * "string 99". Return false when that isn't possible.
  109.  */
  110.     {
  111.     unsigned char *c;
  112.  
  113.     c = s + s[0];        /* c points to very last character */
  114.  
  115.     if(*c < '0' || *c > '9' || *(c-1) < '0' || *(c-1) > '9')    /* need to append 00? */
  116.         {
  117.         s[0] += 3;
  118.         *++c = ' ';
  119.         *++c = '0';
  120.         *++c = '0';
  121.         }
  122.     else
  123.         {
  124.         *c += 1;
  125.         if(*c > '9')
  126.             {
  127.             *c-- = '0';
  128.             *c += 1;
  129.             if(*c > '9')
  130.                 return 0;
  131.             }
  132.         }
  133.     return 1;
  134.     }
  135.  
  136.  
  137. EasyPPCSession NewEasyPPCSession(StringPtr name,OSType type)
  138.     {
  139.     EasyPPCSession es;
  140.     PPCOpenPBRec opbr;
  141.     PPCPortRec portName;
  142.     OSErr thisError;
  143.     short i;
  144.  
  145.     es = (void *)NewPtr(sizeof(EasyPPCSessionRecord));
  146.  
  147.     portName.nameScript = 0;
  148.     MoveString(name,portName.name);
  149.     portName.portKindSelector = ppcByCreatorAndType;
  150.     portName.u.port.creator = kEasyPPCPortCreator;
  151.     portName.u.port.type = type;
  152.  
  153.     opbr.ioCompletion = 0;
  154.     opbr.serviceType = ppcServiceRealTime;
  155.     opbr.resFlag = 0;
  156.     opbr.portName = &portName;
  157.     opbr.locationName = 0;
  158.     opbr.networkVisible = 1;
  159.  
  160. tryOpen:
  161.     thisError = PPCOpenSync(&opbr);
  162.  
  163.     if(thisError == portNameExistsErr)
  164.         if(BumpStringNumber(portName.name))
  165.             goto tryOpen;
  166.  
  167.     if(thisError)
  168.         goto fail;
  169.  
  170.     es->portRefNum = opbr.portRefNum;
  171.     es->type = type;
  172.     es->serverType = type;
  173.     thisError = GetDefaultUser(0,es->userName);
  174.  
  175.     es->waitingToWrite = 0;
  176.     for(i = 0; i < kEasyPPCWritePacketCount; i++)
  177.         es->wpbr[i].used = 0;
  178.  
  179.     es->connected = 0;
  180.     for(i = 0; i < kEasyPPCClientCount; i++)
  181.         es->client[i].used = 0;
  182.  
  183.     goto goHome;
  184. fail:
  185.     DisposePtr((Ptr)es);
  186.     es = 0;
  187. goHome:
  188.     return es;
  189.     }
  190.  
  191.  
  192. void DisposeEasyPPCSession(EasyPPCSession es)
  193.     {
  194.     EasyPPCWritePB *ewpb;
  195.     PPCClosePBRec cpbr;
  196.     short i;
  197.  
  198.     if(es)
  199.         {
  200.         cpbr.ioCompletion = 0;
  201.         cpbr.portRefNum = es->portRefNum;
  202.     
  203.         PPCCloseSync(&cpbr);
  204.  
  205.         for(i = 0; i < kEasyPPCWritePacketCount; i++)
  206.             {
  207.             ewpb = &es->wpbr[i];
  208.  
  209.             if(ewpb->used && ewpb->buffer)
  210.                 DisposePtr(ewpb->buffer);            /* easymanage */
  211.             }
  212.         }
  213.     }
  214.  
  215.  
  216. OSErr ConnectEasyPPCSession(EasyPPCSession es,
  217.         LocationNameRec *locationName,PortInfoRec *pir,long *sessRefNum)
  218.     {
  219.     PPCStartPBRec spbr;
  220.     OSErr thisError;
  221.     EasyPPCClient *clientPtr;
  222.  
  223.     if(!es || es->connected >= kEasyPPCClientCount)            /* already enough connected */
  224.         {
  225.         thisError = -1;
  226.         goto goHome;
  227.         }
  228.  
  229.     spbr.ioCompletion = 0;
  230.     spbr.portRefNum = es->portRefNum;
  231.     spbr.serviceType = ppcServiceRealTime;
  232.     spbr.resFlag = 0;
  233.     spbr.portName = &pir->name;
  234.     spbr.locationName = locationName;
  235.     spbr.userData = 0;
  236.     spbr.userRefNum = 0;
  237.  
  238.     thisError = PPCStartSync(&spbr);
  239.  
  240.     if(thisError == guestNotAllowedErr)
  241.         {
  242.         Boolean asGuest;
  243.  
  244.         thisError = StartSecureSession(&spbr,
  245.                 (StringPtr)0x910,
  246.                 true,                /* use default? */
  247.                 false,                /* don't allow guest, it didn't work */
  248.                 &asGuest,
  249.                 "\p");
  250.         }
  251.  
  252.     if(!thisError)
  253.         {
  254.         clientPtr = FindFreeClient(es);
  255.  
  256.         InitializeClient(es,clientPtr);
  257.         clientPtr->userName[0] = 0;
  258.         clientPtr->locationName = *locationName;
  259.         clientPtr->portName = pir->name;
  260.         clientPtr->sessRefNum = spbr.sessRefNum;
  261.         }
  262. goHome:
  263.     if(sessRefNum)
  264.         *sessRefNum = spbr.sessRefNum;
  265.     return thisError;
  266.     }
  267.  
  268.  
  269. /* ---------------------------------------------------------- */
  270.  
  271.  
  272. OSErr DisconnectEasyPPCSession(EasyPPCSession es,long sessRefNum)
  273.     {
  274.     PPCEndPBRec epbr;
  275.     OSErr thisError;
  276.     EasyPPCClient *clientPtr;
  277.  
  278.     if(!es)
  279.         return -1;
  280.  
  281.     clientPtr = FindClient(es,sessRefNum);
  282.     if(!clientPtr)
  283.         return -1;
  284.  
  285.     epbr.ioCompletion = 0;
  286.     epbr.sessRefNum = clientPtr->sessRefNum;
  287.     thisError = PPCEndSync(&epbr);
  288.  
  289.     RemoveClientEntry(es,clientPtr);
  290.  
  291.     HUnlock((void *)es->client);
  292.  
  293.     return thisError;
  294.     }
  295.  
  296.  
  297. /* ---------------------------------------------------------- */
  298.  
  299.  
  300. OSErr LetConnectEasyPPCSession(EasyPPCSession es)
  301.     {
  302.     OSErr thisError;
  303.     EasyPPCClient *clientPtr;
  304.  
  305.     /*
  306.      * Enough connected?
  307.      */
  308.     if(!es || es->connected >= kEasyPPCClientCount)
  309.         {
  310.         thisError = -1;
  311.         goto goHome;
  312.         }
  313.  
  314.     clientPtr = FindFreeClient(es);
  315.  
  316.     InitializeClient(es,clientPtr);
  317.     clientPtr->sessRefNum = 0;
  318.     clientPtr->waitingToConnect = 1;
  319.  
  320.     clientPtr->ipbr.ioCompletion = (ProcPtr)InformCompletion;
  321.     clientPtr->ipbr.portRefNum = es->portRefNum;
  322.     clientPtr->ipbr.autoAccept = 0;
  323.     clientPtr->ipbr.portName = &clientPtr->portName;
  324.     clientPtr->ipbr.locationName = &clientPtr->locationName;
  325.     clientPtr->ipbr.userName = clientPtr->userName;
  326.  
  327.     thisError = PPCInformAsync(&clientPtr->ipbr);
  328.  
  329. goHome:
  330.     return thisError;
  331.     }
  332.  
  333. pascal void InformCompletion(PPCParamBlockPtr pb)
  334. /*
  335.  * Here, we only accept the connection if
  336.  * it's not a 'test' connection.
  337.  * If it _is_ a test, we return 'test' as the
  338.  * Reject-reason.
  339.  */
  340.     {
  341.     PPCInformPBRec *ipbr;
  342.     PPCAcceptPBRec apbr;
  343.     PPCRejectPBRec rpbr;
  344.  
  345.     ipbr = (PPCInformPBRec *)pb;
  346.  
  347.     if(ipbr->ioResult)            /* problem? maybe the port's being closed? */
  348.         return;                    /* just quit it. */
  349.  
  350.     if(ipbr->userData != testConnection)
  351.         {
  352.         apbr.ioCompletion = 0;
  353.         apbr.sessRefNum = ipbr->sessRefNum;
  354.         PPCAcceptSync(&apbr);
  355.         }
  356.     else
  357.         {
  358.         rpbr.ioCompletion = 0;
  359.         rpbr.sessRefNum = ipbr->sessRefNum;
  360.         rpbr.rejectInfo = testConnection;
  361.         PPCRejectSync(&rpbr);
  362.         PPCInformAsync(ipbr);
  363.         }
  364.     }
  365.  
  366.  
  367. OSErr WriteEasyPPCSession(EasyPPCSession es,long sessRefNum,
  368.         long packetType,void *buffer,long length,Boolean easyManage)
  369. /*
  370.  * If 'easyManage' is true, then BigEasyPPC makes a local copy
  371.  * of the data, and the caller is free to forget about his copy.
  372.  */
  373.     {
  374.     OSErr result;
  375.     PPCWritePBRec *wpb;
  376.     EasyPPCWritePB *ewpb;
  377.     short i;
  378.     EasyPPCClient *clientPtr;
  379.  
  380.     if(!es || (es->waitingToWrite >= kEasyPPCWritePacketCount) )
  381.         {
  382.         result = 1;
  383.         goto goHome;
  384.         }
  385.  
  386.     clientPtr = FindClient(es,sessRefNum);
  387.     if(!clientPtr)
  388.         {
  389.         result = 1;
  390.         goto goHome;
  391.         }
  392.  
  393.     es->waitingToWrite ++;
  394.  
  395.     for(i = 0; i < kEasyPPCWritePacketCount; i++)
  396.         {
  397.         ewpb = &es->wpbr[i];
  398.         if(!ewpb->used)
  399.             goto gotOne;
  400.         }
  401.  
  402.     result = 1;                /* this should never happen! */
  403.     Debugger();
  404.     goto goHome;
  405.     
  406. gotOne:
  407.     ewpb->used = 1;
  408.  
  409.     if(easyManage)
  410.         {
  411.         ewpb->buffer = NewPtr(length);
  412.         if(!ewpb->buffer)
  413.             DebugStr("\pCouldn't allocate ppc buffer copy! Whoa!");
  414.         BlockMove(buffer,ewpb->buffer,length);
  415.         buffer = ewpb->buffer;
  416.         }
  417.     else
  418.         ewpb->buffer = 0;
  419.  
  420.     wpb = &ewpb->wpbr;
  421.  
  422.     wpb->ioCompletion = 0;
  423.     wpb->sessRefNum = clientPtr->sessRefNum;
  424.     wpb->bufferLength = length;
  425.     wpb->bufferPtr = buffer;
  426.     wpb->more = 0;
  427.     wpb->userData = length;
  428.     wpb->blockCreator = 0;
  429.     wpb->blockType = packetType;
  430.  
  431.     result = PPCWriteAsync(wpb);
  432. goHome:
  433.     return result;
  434.     }
  435.  
  436.  
  437. OSErr ReadEasyPPCSession(EasyPPCSession es,long sessRefNum,void *buffer,long length)
  438.     {
  439.     OSErr result;
  440.     EasyPPCClient *clientPtr;
  441.  
  442.     if(!es)
  443.         {
  444.         result = 1;
  445.         goto goHome;
  446.         }
  447.  
  448.     clientPtr = FindClient(es,sessRefNum);
  449.  
  450.     if(!clientPtr || clientPtr->waitingToReadLength || clientPtr->waitingToReadData)
  451.         {
  452.         result = 1;
  453.         goto goHome;
  454.         }
  455.  
  456.     clientPtr->waitingToReadData = 1;
  457.  
  458.     *(long *)buffer = clientPtr->tinyBuffer;
  459.  
  460.     if(clientPtr->waitingDataSize > 4)
  461.         {
  462.         clientPtr->rpbr.ioCompletion = 0;
  463.         clientPtr->rpbr.sessRefNum = clientPtr->sessRefNum;
  464.         clientPtr->rpbr.bufferLength = length - 4;
  465.         clientPtr->rpbr.bufferPtr = (void *) ( (long)buffer + 4 );
  466.  
  467.         if(clientPtr->rpbr.bufferLength < 0)
  468.             clientPtr->rpbr.bufferLength = 0;
  469.  
  470.         result = PPCReadAsync(&clientPtr->rpbr);
  471.         }
  472. goHome:
  473.     return result;
  474.     }
  475.  
  476.  
  477. /* ---------------------------------------------------------- */
  478.  
  479.  
  480. void PollEasyPPCClient(EasyPPCSession es,EasyPPCClient *clientPtr,
  481.         EasyPPCPollResult *pollResult)
  482.     {
  483.     /*
  484.      * Should we start up the read process?
  485.      */
  486.     if(!clientPtr->waitingToReadLength && !clientPtr->waitingToReadData &&
  487.             clientPtr->sessRefNum)        /* neither? */
  488.         {
  489.         clientPtr->waitingToReadLength = 1;
  490.  
  491.         clientPtr->rpbr.ioCompletion = 0;
  492.         clientPtr->rpbr.sessRefNum = clientPtr->sessRefNum;
  493.         clientPtr->rpbr.bufferLength = 4;
  494.         clientPtr->rpbr.bufferPtr = (void *)&clientPtr->tinyBuffer;
  495.  
  496.         pollResult->error = PPCReadAsync(&clientPtr->rpbr);
  497.         if(pollResult->error)
  498.             {
  499.             pollResult->operation = 1;
  500.             pollResult->sessRefNum = clientPtr->sessRefNum;
  501.             pollResult->length = 0;
  502.             pollResult->packetType = 0;
  503.             pollResult->buffer = 0;
  504.             goto goHome;
  505.             }
  506.         }
  507.  
  508.     /*
  509.      * Received a length datum?
  510.      */
  511.     if(clientPtr->waitingToReadLength && clientPtr->rpbr.ioResult != 1)
  512.         {
  513.         clientPtr->waitingToReadLength = 0;
  514.         clientPtr->waitingDataSize = clientPtr->rpbr.userData;
  515.  
  516.         pollResult->operation = easyPPCSessionMessageWaiting;
  517.         pollResult->error = clientPtr->rpbr.ioResult;
  518.         pollResult->sessRefNum = clientPtr->rpbr.sessRefNum;
  519.         pollResult->length = clientPtr->rpbr.userData;
  520.         pollResult->packetType = clientPtr->rpbr.blockType;
  521.         pollResult->buffer = 0;
  522.         goto goHome;
  523.         }
  524.  
  525.     /*
  526.      * Received a message?
  527.      */
  528.     if(clientPtr->waitingToReadData &&
  529.             (clientPtr->waitingDataSize < 4 || clientPtr->rpbr.ioResult != 1) )
  530.         {
  531.         clientPtr->waitingToReadData = 0;
  532.         clientPtr->waitingDataSize = 0;
  533.  
  534.         pollResult->operation = easyPPCSessionMessageRead;
  535.         pollResult->error = clientPtr->rpbr.ioResult;
  536.         pollResult->sessRefNum = clientPtr->rpbr.sessRefNum;
  537.         pollResult->length = clientPtr->rpbr.userData;
  538.         pollResult->packetType = clientPtr->rpbr.blockType;
  539.         pollResult->buffer = clientPtr->rpbr.bufferPtr;
  540.  
  541.         if(clientPtr->rpbr.more && !pollResult->error)        /* don't handle part-reads very well. */
  542.             Debugger();
  543.         goto goHome;
  544.         }
  545.  
  546.     /*
  547.      * Someone connect to us?
  548.      */
  549.     if(clientPtr->waitingToConnect && clientPtr->ipbr.ioResult != 1)
  550.         {
  551.         if(clientPtr->ipbr.userData != testConnection)
  552.             {
  553.             clientPtr->waitingToConnect = 0;
  554.             clientPtr->sessRefNum = clientPtr->ipbr.sessRefNum;
  555.     
  556.             pollResult->operation = easyPPCSessionJustConnected;
  557.             pollResult->error = clientPtr->ipbr.ioResult;
  558.             pollResult->sessRefNum = clientPtr->ipbr.sessRefNum;
  559.             pollResult->length = 0;
  560.             pollResult->packetType = 0;
  561.             pollResult->buffer = 0;
  562.             goto goHome;
  563.             }
  564.         }
  565.  
  566.     /*
  567.      * No activity?
  568.      */
  569.     pollResult->operation = easyPPCSessionIdle;
  570.     pollResult->error = 0;
  571.     pollResult->sessRefNum = 0;
  572.     pollResult->length = 0;
  573.     pollResult->packetType = 0;
  574.     pollResult->buffer = 0;
  575.  
  576. goHome:
  577.     HandleSomeErrors(es,pollResult);
  578.     }
  579.  
  580.  
  581. /* ---------------------------------------------------------- */
  582.  
  583.  
  584. void PollEasyPPCSession(EasyPPCSession es,EasyPPCPollResult *pollResult)
  585.     {
  586.     unsigned short i,j;
  587.     EasyPPCWritePB *ewpb;
  588.     PPCWritePBRec *wpb;
  589.     EasyPPCClient *clientPtr;
  590.  
  591.     es->fairSeed++;
  592.     if(es->fairSeed & 1)
  593.         goto checkOutgoing;
  594.  
  595.     /*
  596.      * Every poll, switch which 
  597.      * client gets checked first.
  598.      */
  599.     es->fairClient++;
  600.     j = es->fairClient;
  601.  
  602.     for(i = 0; i < kEasyPPCClientCount; i++)
  603.         {
  604.         clientPtr = &es->client[ (i + j) % kEasyPPCClientCount];
  605.  
  606.         if(clientPtr->used)
  607.             {
  608.             PollEasyPPCClient(es,clientPtr,pollResult);
  609.             if(pollResult->operation != easyPPCSessionIdle)
  610.                 goto goHome;
  611.             }
  612.         }
  613.  
  614.  
  615. checkOutgoing:
  616.     /*
  617.      * Sent a message?
  618.      */
  619.     if(es->waitingToWrite)
  620.         {
  621.         es->fairWrite ++;
  622.         j = es->fairWrite + TickCount();
  623.         for(i = 0; i < kEasyPPCWritePacketCount; i++)
  624.             {
  625.             ewpb = &es->wpbr[(i + j) % kEasyPPCWritePacketCount];
  626.             wpb = &ewpb->wpbr;
  627.             if(ewpb->used && wpb->ioResult != 1)
  628.                 {
  629.                 es->waitingToWrite --;
  630.                 ewpb->used = 0;
  631.  
  632.  
  633.                 pollResult->operation = easyPPCSessionMessageWritten;
  634.                 pollResult->error = wpb->ioResult;
  635.                 pollResult->sessRefNum = wpb->sessRefNum;
  636.                 pollResult->packetType = wpb->blockType;
  637.                 pollResult->length = wpb->userData;
  638.  
  639.                 if(ewpb->buffer)
  640.                     {
  641.                     DisposePtr(ewpb->buffer);        /* easymanage */
  642.                     pollResult->buffer = 0;
  643.                     }
  644.                 else
  645.                     pollResult->buffer = wpb->bufferPtr;                    
  646.  
  647.                 goto goHome;
  648.                 }
  649.             }
  650.         }
  651.  
  652.     pollResult->operation = easyPPCSessionIdle;
  653.     pollResult->error = 0;
  654.     pollResult->sessRefNum = 0;
  655.     pollResult->length = 0;
  656.     pollResult->packetType = 0;
  657.     pollResult->buffer = 0;
  658.  
  659. goHome:
  660.     HandleSomeErrors(es,pollResult);
  661.     }
  662.  
  663. void HandleSomeErrors(EasyPPCSession es,EasyPPCPollResult *pollResult)
  664. /*
  665.  * Handle some types of PPC errors, and modify
  666.  * the result accordingly.
  667.  */
  668.     {
  669.     EasyPPCClient *clientPtr;
  670.  
  671.     switch(pollResult->error)
  672.         {
  673.         case sessClosedErr:
  674.         case noSessionErr:
  675.             pollResult->error = easyPPCSessionOtherPortGone;
  676.             /*
  677.              * There may be no client, if we're just
  678.              * clearing out the stale outgoing-messages.
  679.              */
  680.             clientPtr = FindClient(es,pollResult->sessRefNum);
  681.             if(clientPtr)
  682.                 RemoveClientEntry(es,clientPtr);
  683.             break;
  684.         default:
  685.             if(pollResult->error < 0)
  686.                 Debugger();
  687.             break;
  688.         }
  689.     }
  690.  
  691. /* ---------------------------------------------------------- */
  692.  
  693. OSErr BrowseAndConnectEasyPPCSession(EasyPPCSession es,
  694.         StringPtr prompt, StringPtr applListLabel,long *sessRefNum,
  695.         LocationNameRec *location,PortInfoRec *portInfo)
  696.     {
  697.     OSErr thisError;
  698.  
  699.     if(es->connected >= kEasyPPCClientCount)        /* enough connections? */
  700.         {
  701.         thisError = easyPPCSessionTooManyConnections;
  702.         goto goHome;
  703.         }
  704.  
  705.     gEasyFilterSession = es;            /* great, pass arguments in global */
  706.  
  707.     thisError = PPCBrowser(prompt,
  708.             applListLabel,
  709.             gEverBrowsed,
  710.             &gTheLocation,
  711.             &gThePortInfo,
  712.             EasyBrowserFilter,
  713.             0);
  714.  
  715.     gEverBrowsed = true;
  716.  
  717.     if(thisError)
  718.         goto goHome;
  719.  
  720.     thisError = ConnectEasyPPCSession(es,&gTheLocation,&gThePortInfo,sessRefNum);
  721.  
  722.     if(location)
  723.         *location = gTheLocation;
  724.     if(portInfo)
  725.         *portInfo = gThePortInfo;
  726.  
  727. goHome:
  728.     return thisError;
  729.     }
  730.  
  731. pascal Boolean EasyBrowserFilter (LocationNamePtr location, PortInfoPtr port)
  732. /*
  733.  * If the port has the same type as us, and our servertype is our own type,
  734.  * then guest access must be enabled, and a test connection is attempted.
  735.  *
  736.  * If the servertype is different, and we find one of that kind, then a
  737.  * connection is attempted, but, if "guest not allowed" is returned, we
  738.  * assume that it's okay to try, later, with the password, and allow it in
  739.  * the browser.
  740.  */
  741.     {
  742.     OSErr thisError;
  743.  
  744.     if (port->name.u.port.creator == kEasyPPCPortCreator
  745.             && port->name.u.port.type == gEasyFilterSession->serverType)
  746.         {
  747.         /*
  748.          * Try to connect to it, to see if it's available
  749.          */
  750.         PPCStartPBRec spbr;
  751.         PPCEndPBRec epbr;
  752.  
  753.         spbr.ioCompletion = 0;
  754.         spbr.portRefNum = gEasyFilterSession->portRefNum;
  755.         spbr.serviceType = ppcServiceRealTime;
  756.         spbr.resFlag = 0;
  757.         spbr.portName = &port->name;
  758.         spbr.locationName = location;
  759.         spbr.userData = testConnection;
  760.         spbr.userRefNum = 0;
  761.  
  762.         thisError = PPCStartSync(&spbr);
  763.         if(!thisError)                        /* shouldn't accept, but... */
  764.             {
  765.             epbr.ioCompletion = 0;
  766.             epbr.sessRefNum = spbr.sessRefNum;
  767.             PPCEndSync(&epbr);
  768.             return false;
  769.             }
  770.         else if(thisError == guestNotAllowedErr)
  771.             return true;
  772.         else
  773.             {
  774.             if(thisError == userRejectErr && spbr.rejectInfo == testConnection)
  775.                 return true;
  776.             else
  777.                 return false;
  778.             }
  779.         }
  780.     else
  781.         return false;
  782.     }
  783.  
  784.  
  785. /* ---------------------------------------------------------- */
  786. void FindNamesEasyPPCSession(EasyPPCSession es,long sessRefNum,
  787.         StringPtr zoneName,StringPtr macName,StringPtr portName)
  788. /*
  789.  * Return the names of the Macintosh we're connected to.
  790.  */
  791.     {
  792.     EasyPPCClient *clientPtr;
  793.     StringPtr s;
  794.  
  795.     clientPtr = FindClient(es,sessRefNum);
  796.     if(clientPtr)
  797.         {
  798.         if(zoneName)
  799.             {
  800.             s = clientPtr->locationName.u.nbpEntity.zoneStr;
  801.             if(s[0] && clientPtr->locationName.locationKindSelector
  802.                     == ppcNBPLocation)
  803.                 MoveString(s,zoneName);
  804.             else
  805.                 MoveString("\p<Local>",zoneName);
  806.             }
  807.  
  808.         if(macName)
  809.             {
  810.             s = clientPtr->locationName.u.nbpEntity.objStr;
  811.             if(s[0] && clientPtr->locationName.locationKindSelector
  812.                     == ppcNBPLocation)
  813.                 MoveString(s,macName);
  814.             else
  815.                 MoveString("\p<This Macintosh>",macName);
  816.             }
  817.  
  818.         if(portName)
  819.             MoveString(clientPtr->portName.name,portName);
  820.         }
  821.     else
  822.         {
  823.         if(zoneName)
  824.             zoneName[0] = 0;
  825.         if(macName)
  826.             macName[0] = 0;
  827.         if(portName)
  828.             portName[0] = 0;
  829.         }
  830.     }
  831.  
  832.  
  833.  
  834. /* ---------------------------------------------------------- */
  835.  
  836. void InitializeClient(EasyPPCSession es,EasyPPCClient *clientPtr)
  837. /*
  838.  * Initialize just this client, as if it's
  839.  * just sitting there.
  840.  */
  841.     {
  842.     #pragma unused (es)
  843.  
  844.     clientPtr->sessRefNum = 0;
  845.  
  846.     clientPtr->waitingToConnect = 0;
  847.     clientPtr->waitingToReadData = 0;
  848.     clientPtr->waitingToReadLength = 0;
  849.     }
  850.  
  851. /* ---------------------------------------------------------- */
  852.  
  853. EasyPPCClient *FindClient(EasyPPCSession es,long sessRefNum)
  854. /*
  855.  * Do a linear search of the EasyPPCSession's
  856.  * clients, and return a pointer to the
  857.  * client specified.
  858.  *
  859.  * sessRefNum nil==0 matches to the first client.
  860.  * So, an app that only has one connection need not remember
  861.  * its refNum.
  862.  *
  863.  * If there isn't a match, return nil.
  864.  */
  865.     {
  866.     short i;
  867.     EasyPPCClient *w;
  868.  
  869.     if(!es->connected)
  870.         {
  871.         w = 0;
  872.         goto goHome;
  873.         }
  874.  
  875.     if(sessRefNum == 0)
  876.         {
  877.         w = &es->client[0];
  878.         if(!w->sessRefNum)        /* Not a good choice, if not really connected */
  879.             w = 0;
  880.         goto goHome;
  881.         }
  882.  
  883.     for(i = 0; i < kEasyPPCClientCount; i++)
  884.         {
  885.         w = &es->client[i];
  886.         if(w->used && w->sessRefNum == sessRefNum)
  887.             goto goHome;
  888.         }
  889.     w = 0;
  890.  
  891. goHome:
  892.     return w;
  893.     }
  894.  
  895.  
  896. /* ---------------------------------------------------------- */
  897.  
  898. void RemoveClientEntry(EasyPPCSession es,EasyPPCClient *clientPtr)
  899. /*
  900.  * Remove client number 'n' from the list.
  901.  * Assume the list is locked, already.
  902.  * Also, unmark any outgoing packets for that session.
  903.  */
  904.     {
  905.     /*
  906.      * Remove any waiting outgoing packets
  907.      */
  908.  
  909.     clientPtr->used = 0;
  910.     es->connected --;
  911.     }
  912.  
  913.  
  914. /* ---------------------------------------------------------- */
  915.  
  916. EasyPPCClient *FindFreeClient(EasyPPCSession es)
  917.     {
  918.     short i;
  919.     EasyPPCClient *clientPtr;
  920.  
  921.     for(i = 0; i < kEasyPPCClientCount; i++)
  922.         {
  923.         clientPtr = &es->client[i];
  924.  
  925.         if(!clientPtr->used)
  926.             {
  927.             clientPtr->used = 1;
  928.             es->connected ++;
  929.             goto goHome;
  930.             }
  931.         }
  932.  
  933.     clientPtr = 0;
  934.     Debugger(); //!!! should _never_ happen.
  935. goHome:
  936.     return clientPtr;
  937.     }
  938.  
  939. /* ---------------------------------------------------------- */
  940.  
  941.  
  942. void SetServerTypeEasyPPCSession(EasyPPCSession es,OSType serverType)
  943.     {
  944.     es->serverType = serverType;
  945.     }
  946.  
  947.  
  948.  
  949.